package main

import (
	"context"
	"fmt"
	"os/exec"
	"time"
)

// 需求：shell命令执行时间过长，需要强制杀死任务

type result struct {
	err    error
	output []byte
}

func main() {
	// 执行1个cmd，让它在一个协程里去执行，让它执行2秒：sleep 2;echo hello;
	// 1秒的时候，杀死cmd

	var (
		ctx        context.Context    // 上下文，感知channel
		cancelFunc context.CancelFunc // 取消函数，关闭channel
		cmd        *exec.Cmd
		resultChan chan *result
		res        *result
	)

	// 创建了一个结果队列
	resultChan = make(chan *result, 1000)

	// context: chan byte
	// cancelFunc: close(chan byte)

	ctx, cancelFunc = context.WithCancel(context.TODO())

	go func() {
		var (
			output []byte
			err    error
		)
		cmd = exec.CommandContext(ctx, "D:\\cygwin64\\bin\\bash.exe", "-c", "sleep 2;echo hello")

		// select { case <- ctx.Done(): }
		// kill pid, 进程ID，杀死子进程
		// cancelFunc相当于一个select，可以在主协程杀死在其他协程中对应的context，从而达到杀死子进程

		// 执行任务，捕获输出
		output, err = cmd.CombinedOutput()

		// 把任务输出结果，传给main协程
		resultChan <- &result{
			err:    err,
			output: output,
		}
	}()

	// 继续往下走
	time.Sleep(1 * time.Second)
	// 取消上下文
	cancelFunc()

	// 在main协程里，等待协程的退出，并打印任务执行结果
	res = <-resultChan

	// 打印任务执行结果
	fmt.Println(res.err, string(res.output)) // exit status 1 表示出错，output是空的
}
